package org.ala.linshen.dp;

/**
 * 给你整数 zero ，one ，low 和 high ，我们从空字符串开始构造一个字符串，每一步执行下面操作中的一种：
 *
 * 将 '0' 在字符串末尾添加 zero  次。
 * 将 '1' 在字符串末尾添加 one 次。
 * 以上操作可以执行任意次。
 *
 * 如果通过以上过程得到一个 长度 在 low 和 high 之间（包含上下边界）的字符串，那么这个字符串我们称为 好 字符串。
 *
 * 请你返回满足以上要求的 不同 好字符串数目。由于答案可能很大，请将结果对 109 + 7 取余 后返回。
 *
 *
 *
 * 示例 1：
 *
 * 输入：low = 3, high = 3, zero = 1, one = 1
 * 输出：8
 * 解释：
 * 一个可能的好字符串是 "011" 。
 * 可以这样构造得到："" -> "0" -> "01" -> "011" 。
 * 从 "000" 到 "111" 之间所有的二进制字符串都是好字符串。
 * 示例 2：
 *
 * 输入：low = 2, high = 3, zero = 1, one = 2
 * 输出：5
 * 解释：好字符串为 "00" ，"11" ，"000" ，"110" 和 "011" 。
 *
 *
 * 提示：
 *
 * 1 <= low <= high <= 105
 * 1 <= zero, one <= low
 * @author ala
 * @data 2024-09-13 09:38
 */
public class Q2466 {

    public static void main(String[] args) {
        Q2466 q = new Q2466();

//        int low = 3, high = 3, zero = 1, one = 1;
//        int low = 2, high = 3, zero = 1, one = 2;
//        int low = 200, high = 200, zero = 10, one = 1;
        int low = 500, high = 500, zero = 5, one = 2;

        System.out.println(q.countGoodStrings(low, high, zero, one));
    }

    public int countGoodStrings(int low, int high, int zero, int one) {
        return V1(low, high, zero, one);
    }
    static int MOD = (int)1e9 + 7;
    /**
     *  有两种面额的硬币，[zero, one]，这两种面额可以无限用，组成价值在[low, high]的方案数
     */
    protected int V1(int low, int high, int zero, int one) {
        int[] coins = {zero, one};
        int[] dp = new int[high + 1];
        for (int c : coins) { dp[c] += 1; }

        int res = 0;
        for (int i = Math.min(zero, one) ; i <= high ; i++) {
            for (int c : coins) {
                if (i - c >= 0) {dp[i] = (dp[i] + dp[i - c]) % MOD;}
            }
            if (i >= low && i <= high) {
                res = (res + dp[i]) % MOD;
            }
        }
        return res;
    }


}
